package com.github.cosycode.imgtool.action;

import com.github.cosycode.common.util.io.FileSystemUtils;
import com.github.cosycode.common.util.otr.PrintTool;
import com.github.cosycode.flow.base.AbstractAction;
import com.github.cosycode.imgtool.ctrl.MarkdownFileProcessor;
import com.github.cosycode.imgtool.rule.CheckConfig;
import com.github.cosycode.imgtool.rule.FileExistCheckBRO;
import com.google.gson.GsonBuilder;
import lombok.Data;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * <b>Description : </b> 检查指定文件夹文件下面的 markdown 文件中图片链接是否可以正确匹配, 并打印结果
 * <p>
 * <b>created in </b> 2022/12/26
 * </p>
 *
 * @author pengfchen
 * @since 1.0
 **/
@Slf4j
public class MarkdownImageLinkCheckAction extends AbstractAction<MarkdownImageLinkCheckAction.MarkdownProjectImageLinkExistReport> {

    /**
     * check 配置
     */
    private final CheckConfig checkConfig;
    private final String scanPath;

    public MarkdownImageLinkCheckAction(@NonNull CheckConfig checkConfig, @NonNull String scanPath) {
        this.checkConfig = checkConfig;
        this.scanPath = scanPath;
    }

    /**
     * 扫描文件夹下的所有 md 文件, 并标记出找不到对应图片的 URL
     *
     * @param scanPath 扫描路径
     * @return 分析的信息 Map &lt; key: 文件路径, value: {@link FileExistCheckBRO} &gt;
     */
    public static Map<String, List<FileExistCheckBRO>> scanAndAnalyzeMdImgExistCondition(CheckConfig checkConfig, String scanPath) throws FileNotFoundException {
        final File file = new File(scanPath);
        Map<String, List<FileExistCheckBRO>> map = new HashMap<>();
        List<File> fileList = FileSystemUtils.findFileFromDir(file, f -> f.getName().endsWith(".md"), true);
        for (File f : fileList) {
            try {
                List<FileExistCheckBRO> list = new ArrayList<>();
                MarkdownFileProcessor.findMdImgLink(f, checkConfig, list::add);
                map.put(f.getPath(), list);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return map;
    }

    /**
     * 检查一个项目下 markdown
     * 匹配 markdown 文件: 项目中的 markdown 文件
     * img 引用匹配类型: markdown 中所有的 img path 类型
     * img 文件夹: 项目源文件夹
     * 匹配策略: 全路径匹配
     */
    public static void main(String[] args) throws Exception {
        final String rootPath = "P:\\git-note\\working-note";
        CheckConfig config = CheckConfig.geneConfig(true, rootPath, true);
        MarkdownImageLinkCheckAction checkAction = new MarkdownImageLinkCheckAction(config, rootPath);
        MarkdownProjectImageLinkExistReport report = checkAction.doProcess();
        report.printDanglingLink();
        report.printMatchLink();
        PrintTool.info(new GsonBuilder().setPrettyPrinting().create().toJson(report));
    }

    @Override
    public MarkdownProjectImageLinkExistReport doProcess() throws Exception {
        Map<String, List<FileExistCheckBRO>> stringListMap = scanAndAnalyzeMdImgExistCondition(checkConfig, scanPath);
        MarkdownProjectImageLinkExistReport report = new MarkdownProjectImageLinkExistReport();
        report.setConfig(checkConfig);
        report.setScanPath(scanPath);
        report.setExistConditionMap(stringListMap);
        report.setFileCount(stringListMap.size());
        report.setImageLinkCount(stringListMap.values().stream().mapToInt(List::size).sum());
        return report;
    }

    @Data
    public static class MarkdownProjectImageLinkExistReport {
        private CheckConfig config;
        private String scanPath;
        private int fileCount;
        private int imageLinkCount;
        private Map<String, List<FileExistCheckBRO>> existConditionMap;

        public List<FileExistCheckBRO> getDanglingLinkList() {
            return existConditionMap.entrySet().stream()
                    .flatMap(it -> it.getValue().stream().filter(item -> !item.isExist()))
                    .collect(Collectors.toList());
        }

        /**
         * 未匹配到图片的 link 扫描结果
         */
        public void printDanglingLink() {
            log.info("===> printDanglingLink");
            AtomicBoolean matchFlag = new AtomicBoolean(false);
            existConditionMap.forEach((key, value) -> {
                final List<FileExistCheckBRO> collect = value.stream().filter(it -> !it.isExist()).collect(Collectors.toList());
                if (!collect.isEmpty()) {
                    StringBuilder sb = new StringBuilder();
                    collect.forEach(it -> sb.append("        => [absent]:").append(it).append("\n"));
                    log.info("===> file : {} \n{}", key, sb);
                    matchFlag.set(true);
                }
            });
            if (!matchFlag.get()) {
                log.info(" ===> 未发现未成功匹配到图片的 link");
            }
        }

        /**
         * 打印出匹配到图片的图片的信息
         */
        public void printMatchLink() {
            log.info("===> printMatchLink");
            AtomicBoolean matchFlag = new AtomicBoolean(false);
            existConditionMap.forEach((key, value) -> {
                final List<FileExistCheckBRO> collect = value.stream().filter(FileExistCheckBRO::isExist).collect(Collectors.toList());
                if (!collect.isEmpty()) {
                    StringBuilder sb = new StringBuilder();
                    collect.forEach(it -> sb.append("        => [exist]:").append(it).append("\n"));
                    log.info("===> file : {} \n{}", key, sb);
                    matchFlag.set(true);
                }
            });
            if (!matchFlag.get()) {
                log.info(" ===> 未发现 成功匹配到图片的 link");
            }

        }
    }

}
